////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft Corporation.  All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Portions Copyright (c) 2012 Kentaro Sekimoto  All rights reserved.
////////////////////////////////////////////////////////////////////////////

#ifndef _TOUCH_PANEL_DRIVER_H_
#define _TOUCH_PANEL_DRIVER_H_ 1

#include <tinyhal.h>

//--//

#ifdef GPIO_PFR
#undef GPIO_PFR
#endif
#define GPIO_PFR(pin)  *((volatile UINT32*)(FM4_GPIO_BASE + 0x000UL + ((pin >> 4) << 2)))

#ifdef GPIO_PCR
#undef GPIO_PCR
#endif
#define GPIO_PCR(pin)  *((volatile UINT32*)(FM4_GPIO_BASE + 0x100UL + ((pin >> 4) << 2)))

#ifdef GPIO_DDR
#undef GPIO_DDR
#endif
#define GPIO_DDR(pin)  *((volatile UINT32*)(FM4_GPIO_BASE + 0x200UL + ((pin >> 4) << 2)))

#ifdef GPIO_PDIR
#undef GPIO_PDIR
#endif
#define GPIO_PDIR(pin) *((volatile UINT32*)(FM4_GPIO_BASE + 0x300UL + ((pin >> 4) << 2)))

#ifdef GPIO_PDOR
#undef GPIO_PDOR
#endif
#define GPIO_PDOR(pin) *((volatile UINT32*)(FM4_GPIO_BASE + 0x400UL + ((pin >> 4) << 2)))

#ifdef GPIO_PZR
#undef GPIO_PZR
#endif
#define GPIO_PZR(pin)  *((volatile UINT32*)(FM4_GPIO_BASE + 0x700UL + ((pin >> 4) << 2)))

#ifdef GPIO_MASK
#undef GPIO_MASK
#endif
#define GPIO_MASK(pin)  (1 << (pin & 0xF))

#define FM4_TOUCHPANEL_POLL_TIMESPAN    8000    // 8ms

//A0 - P23-AN15 (A22) XL
//A1 - P20-AN18 (A24) YU
//A2 - P70            XR
//A3 - P71            YD
//A4 - P09-AN19
//A5 - P08-AN20

#define XL_PIN  0x23
#define YU_PIN  0x20
#define XR_PIN  0x70
#define YD_PIN  0x71
#define TOUCH_PIN   YU_PIN
#define AD_X_PIN    YU_PIN
#define AD_X_NO 18
#define AD_X_CH 2
#define AD_Y_PIN    XL_PIN
#define AD_Y_NO 15
#define AD_Y_CH 1

#define GPIO_HI(pin)    {GPIO_DDR(pin) |= GPIO_MASK(pin); GPIO_PDOR(pin) |= GPIO_MASK(pin);}
#define GPIO_LO(pin)    {GPIO_DDR(pin) |= GPIO_MASK(pin); GPIO_PDOR(pin) &= ~GPIO_MASK(pin);}
#define GPIO_IN(pin)    {GPIO_DDR(pin) &= ~GPIO_MASK(pin);}
#define GPIO_HZ(pin)    {GPIO_PZR(pin) |= GPIO_MASK(pin);}
#define GPIO_PU_ON(pin)     {GPIO_PCR(pin) |= GPIO_MASK(pin);}
#define GPIO_PU_OFF(pin)    {GPIO_PCR(pin) &= ~GPIO_MASK(pin);}

#define XR_HI   GPIO_HI(XR_PIN)
#define XR_LO   GPIO_LO(XR_PIN)
#define XR_IN   GPIO_IN(XR_PIN)
#define XR_HZ   GPIO_HZ(XR_PIN)
#define XL_HI   GPIO_HI(XL_PIN)
#define XL_LO   GPIO_LO(XL_PIN)
#define XL_IN   GPIO_IN(XL_PIN)
#define XL_HZ   GPIO_HZ(XL_PIN)
#define YU_HI   GPIO_HI(YU_PIN)
#define YU_LO   GPIO_LO(YU_PIN)
#define YU_IN   GPIO_IN(YU_PIN)
#define YU_HZ   GPIO_HZ(YU_PIN)
#define YD_HI   GPIO_HI(YD_PIN)
#define YD_LO   GPIO_LO(YD_PIN)
#define YD_IN   GPIO_IN(YD_PIN)
#define YD_HZ   GPIO_HZ(YD_PIN)
#define PDINT_IN    GPIO_IN(TO_PIN)

//#define IDLE            {XR_IN;XL_IN;YU_IN;YD_IN;}
//#define SENSE_ON        {XR_LO;XL_LO;YU_IN;YD_IN;GPIO_PFR(TOUCH_PIN) &= ~GPIO_MASK(TOUCH_PIN);GPIO_PU_ON(TOUCH_PIN);}
//#define SENSE_Y_ON      {XR_IN;XL_IN;YU_LO;YD_HI;GPIO_PU_OFF(TOUCH_PIN);}
//#define SENSE_X_ON      {XR_HI;XL_LO;YU_IN;YD_IN;GPIO_PU_OFF(TOUCH_PIN);}
#define IDLE            {XR_IN;XL_IN;YU_HZ;YD_HZ;}
#define SENSE_ON        {XR_LO;XL_LO;YU_IN;YD_HZ;}
#define SENSE_Y_ON      {XR_IN;XL_IN;YU_LO;YD_HI;}
#define SENSE_X_ON      {XR_HI;XL_LO;YU_IN;YD_IN;}

#define TOUCH_CHK       (!(GPIO_PDIR(TOUCH_PIN) & GPIO_MASK(TOUCH_PIN)))
#define AD_Y_ENABLE  {FM4_GPIO->ADE |= GPIO_MASK(AD_Y_NO);  GPIO_PFR(AD_Y_PIN) |= GPIO_MASK(AD_Y_PIN);}
#define AD_Y_DISABLE {FM4_GPIO->ADE &= ~GPIO_MASK(AD_Y_NO); GPIO_PFR(AD_Y_PIN) &= ~GPIO_MASK(AD_Y_PIN);}
#define AD_X_ENABLE  {FM4_GPIO->ADE |= GPIO_MASK(AD_X_NO);  GPIO_PFR(AD_X_PIN) |= GPIO_MASK(AD_X_PIN);}
#define AD_X_DISABLE {FM4_GPIO->ADE &= ~GPIO_MASK(AD_X_NO); GPIO_PFR(AD_X_PIN) &= ~GPIO_MASK(AD_X_PIN);}

// default calibration values
#define X_UL    834
#define Y_UL    657
#define X_DL    880
#define Y_DL    3636
#define X_UR    3351
#define Y_UR    648
#define Y_DR    3587

/*
 * FM4 A-D converter
 * Register Bit Definition
 */
#define ADCR_OVRIE           0x01U
#define ADCR_CMPIE           0x02U
#define ADCR_PCIE            0x04U
#define ADCR_SCIE            0x08U
#define ADCR_CMPIF           0x20U
#define ADCR_PCIF            0x40U
#define ADCR_SCIF            0x80U
#define ADCR_IFALL           (ADCR_CMPIF | ADCR_PCIF | ADCR_SCIF)

#define ADSR_SCS             0x01U
#define ADSR_PCS             0x02U
#define ADSR_PCNS            0x04U
#define ADSR_FDAS            0x40U
#define ADSR_ADSTP           0x80U

#define SCCR_SSTR            0x01U
#define SCCR_SHEN            0x02U
#define SCCR_RPT             0x04U
#define SCCR_SFCLR           0x10U
#define SCCR_SOVR            0x20U
#define SCCR_SFUL            0x40U
#define SCCR_SEMP            0x80U
#define SCFDL_INVL           0x1000U

#define PCCR_PSTR            0x01U
#define PCCR_PHEN            0x02U
#define PCCR_PEEN            0x04U
#define PCCR_ESCE            0x08U
#define PCCR_PFCLR           0x10U
#define PCCR_POVR            0x20U
#define PCCR_PFUL            0x40U
#define PCCR_PEMP            0x80U
#define PCFDL_INVL           0x1000U

#define CMPCR_CMD0           0x20U
#define CMPCR_CMD1           0x40U
#define CMPCR_CMPEN          0x80U

#define ADCEN_ENBL           0x01U
#define ADCEN_READY          0x02U

class KS_MB9BF568_TouchPanel_Driver
{
public:
    static BOOL Initialize(GPIO_INTERRUPT_SERVICE_ROUTINE touchIsrProc);
    static BOOL Uninitialize();
    static HRESULT GetDeviceCaps(unsigned int iIndex, void* lpOutput);
    static void GetPoint(TOUCH_PANEL_SAMPLE_FLAGS* pTipState, int* pSource, int* pUnCalX, int* pUnCalY);
private:
    static void Poll();
    static void TouchCompletion(void* arg);
    static BOOL CalibrationPointGet(TOUCH_PANEL_CALIBRATION_POINT *pTCP);
    //
    INT32 m_global_touch;
    UINT16 m_global_inX;
    UINT16 m_global_inY;
    HAL_COMPLETION    m_touchCompletion;
    INT32 m_samplingTimespan;
};
#endif

